Tidy Tuesday Week 20

Internet Access, US Broadband, data from Microsoft by way of The Verge.

TidyTuesday week 20 | Data from Microsoft and The Verge

Data definition

variable class description
st character 2 letter abbreviation of states in the United States https://www.iso.org/obp/ui/#iso:code:3166:US
county_id double 4 to 5 digit code used to represent the county (last 3 digits) and the state (first digit or first 2 digits) https://www.census.gov/geographies/reference-files.html
county_name character County Name
broadband_availability_per_fcc character percent of people per county with access to fixed terrestrial broadband at speeds of 25 Mbps/3 Mbps as of the end of 2017 https://www.fcc.gov/document/broadband-deployment-report-digital-divide-narrowing-substantially-0
broadband_usage character percent of people per county that use the internet at broadband speeds based on the methodology explained above. Data is from November 2019.

Visualization

# load libaries 
library(tidytuesdayR)
library(tidyverse)
library(urbnmapr)
library(urbnthemes)
library(janitor)
library(colorspace)
library(wesanderson)
library(patchwork)
library(ggstatsplot)
# import data
broadband <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-05-11/broadband.csv')

── Column specification ──────────────────────────────────────────────────────────────────────────────
cols(
  ST = col_character(),
  `COUNTY ID` = col_double(),
  `COUNTY NAME` = col_character(),
  `BROADBAND AVAILABILITY PER FCC` = col_character(),
  `BROADBAND USAGE` = col_character()
)
# clean data 
# reference: Jesse Mostipak  
broadband = broadband %>% janitor::clean_names()
glimpse(broadband)
Rows: 3,143
Columns: 5
$ st                             <chr> "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "…
$ county_id                      <dbl> 1001, 1003, 1005, 1007, 1009, 1011, 1013, 1015, 1017, 1019, 1…
$ county_name                    <chr> "Autauga County", "Baldwin County", "Barbour County", "Bibb C…
$ broadband_availability_per_fcc <chr> "0.81", "0.88", "0.59", "0.29", "0.69", "0.06", "0.78", "0.93…
$ broadband_usage                <chr> "0.28", "0.30", "0.18", "0.07", "0.09", "0.05", "0.11", "0.32…
broadband = broadband %>% mutate(broadband_usage= as.numeric(broadband_usage),
                                 broadband_availability_per_fcc = as.numeric(broadband_availability_per_fcc))
NAs introduced by coercionNAs introduced by coercion
# us counties shp 
counties_sf <- get_urbn_map("counties", sf = TRUE)

U.S. Availability and Usage by County

# availability by county
p1 = counties_sf %>% 
  left_join(broadband, by="county_name") %>%
  #filter(st=="CA") %>%
  ggplot() + 
  geom_sf(mapping = aes(fill = broadband_availability_per_fcc),
          color = "#ffffff", size = 0.25) +
  coord_sf(datum = NA) + 
  scale_fill_gradientn(labels = scales::percent,
                       colours = wes_palette("Zissou1", 100, type = "continuous"), 
                       na.value="grey89",
                       trans="reverse") +
  theme_minimal(base_size = 10) + 
  theme(plot.subtitle=element_text(size=9),
        plot.title=element_text(size=14)) + 
  guides(fill = guide_colorbar(title.position = "top", 
                                title.hjust = .5, 
                                reverse=TRUE,
                                barheight = unit(10, "lines"), 
                                barwidth = unit(.5, "lines"))) +
  labs(fill="",
       title="U.S. Broadband Availability by County",
       subtitle="Percent of people per county with access to fixed terrestrial broadband at speeds of 25 Mbps/3 Mbps, as of the end of 2017")

# usage by county
p2 = counties_sf %>% 
  left_join(broadband, by="county_name") %>%
  #filter(st=="CA") %>%
  ggplot() + 
  geom_sf(mapping = aes(fill = broadband_usage),
          color = "#ffffff", size = 0.25) +
  coord_sf(datum = NA) + 
  scale_fill_gradientn(labels = scales::percent,
                       colours = wes_palette("Zissou1", 100, type = "continuous"), 
                       na.value="grey89",
                       trans="reverse") +
  theme_minimal(base_size = 10) + 
  theme(plot.subtitle=element_text(size=9),
        plot.title=element_text(size=14)) + 
  guides(fill = guide_colorbar(title.position = "top", 
                                title.hjust = .5, 
                                reverse=TRUE,
                                barheight = unit(10, "lines"), 
                                barwidth = unit(.5, "lines"))) +
  labs(fill="",
       title="U.S. Broadband Usage by County",
       subtitle="Percent of people per county that use the internet at broadband speeds of 25 Mbps/3 Mbps, as of November 2019")
p1/ p2 + plot_annotation(caption='TidyTuesday week 20 | Data from The Microsoft') & theme(plot.caption = element_text(hjust=0.5))

Texas: Broadband Availability and Usage

# availability Texas
plot1 = counties_sf %>% filter(state_abbv=="TX") %>%
  left_join(broadband, by="county_name") %>%
  ggplot() + 
  geom_sf(mapping = aes(fill = broadband_availability_per_fcc),
          color = "#ffffff", size = 0.25) +
  coord_sf(datum = NA) + 
  scale_fill_gradientn(labels = scales::percent,
                       colours = wes_palette("Zissou1", 100, type = "continuous"), 
                       na.value="grey89",
                       trans="reverse") +
  theme_minimal(base_size = 10) + 
  theme(plot.subtitle=element_text(size=9),
        plot.title=element_text(size=14)) + 
  guides(fill = guide_colorbar(title.position = "top", 
                                title.hjust = .5, 
                                reverse=TRUE,
                                barheight = unit(10, "lines"), 
                                barwidth = unit(.5, "lines"))) +
  labs(fill="",
       title="Broadband Availability In Texas, U.S.",
       subtitle="Percent of people per county with access to fixed terrestrial broadband at speeds\nof 25 Mbps/3 Mbps, as of the end of 2017")

# Usage Texas
plot2 = counties_sf %>% filter(state_abbv=="TX") %>%
  left_join(broadband, by="county_name") %>%
  ggplot() + 
  geom_sf(mapping = aes(fill = broadband_usage),
          color = "#ffffff", size = 0.25) +
  coord_sf(datum = NA) + 
  scale_fill_gradientn(labels = scales::percent,
                       colours = wes_palette("Zissou1", 100, type = "continuous"), 
                       na.value="grey89",
                       trans="reverse") +
  theme_minimal(base_size = 10) + 
  theme(plot.subtitle=element_text(size=9),
        plot.title=element_text(size=14)) + 
  guides(fill = guide_colorbar(title.position = "top", 
                                title.hjust = .5, 
                                reverse=TRUE,
                                barheight = unit(10, "lines"), 
                                barwidth = unit(.5, "lines"))) +
  labs(fill="",
       title="Broadband Usage In Texas, U.S.",
       subtitle="Percent of people per county that use the internet at broadband speeds of\n25 Mbps/3 Mbps, as of November 2019")
plot1/ plot2 + plot_annotation(caption='TidyTuesday week 20 | Data from Microsoft') & theme(plot.caption = element_text(hjust=0.5))

Broadband Availability by State

broadband %>% drop_na() %>% group_by(st) %>%
  summarise(med = median(broadband_usage)) -> table_median

# boxplot of broadband usage by state
broadband %>% drop_na() %>%
  ggplot(aes(x=reorder(st,broadband_usage), y=broadband_usage)) + 
  geom_boxplot(color="grey60") + 
  geom_point(data=table_median, aes(x= st, y=med, fill=med), shape=23, color="slategrey",show.legend=F) +
  scale_fill_continuous_sequential(palette="Viridis") +
  scale_y_continuous(label=scales::percent) +
  theme_minimal(base_size=10) + 
  theme(panel.grid.minor=element_blank()) +
  coord_flip()

# usage 5 states

# geom_flat_violin function from: https://gist.github.com/dgrtwo/eb7750e74997891d7c20
# reference: https://neuroconscience.wordpress.com/2018/03/15/introducing-raincloud-plots/
# reference: https://bitsandgen.es/my-first-shiny-app-raincloudplots/

pop = c("CA","TX","FL","NY", "PA") # states for plot
broadband_pop = broadband %>% filter(st %in% pop)

broadband_pop %>%
  ggplot(aes(x=fct_rev(st), 
             y=broadband_usage, fill=st, color=st)) + 
  geom_point(position=position_jitter(0.15),size=1.5, alpha=0.6,shape=as.numeric(16)) + 
  geom_flat_violin(position= position_nudge(x=0.25, y=0),adjust=2,alpha=0.9, trim='TRUE',scale='width') +
  geom_boxplot(aes(x=st,y=broadband_usage,fill=st), position=position_nudge(x=0.25, y=0),
               width=0.1, outlier.shape = NA, varwidth=FALSE, color="black", alpha=0.3) + 
  scale_y_continuous(label=scales::percent) +
  scale_fill_manual(values=c("#588b8b","#f28f3b","#457b9d","#c8553d","#5b5f97"))+
  scale_color_manual(values=c("#588b8b","#f28f3b","#457b9d","#c8553d","#5b5f97")) +
  coord_flip() + 
  theme_minimal(base_size = 10) +
  theme(legend.position="none",
        plot.title.position = "plot",
        plot.subtitle=element_text(face="bold", size=10),
        axis.title=element_text(size=9, face="bold"),
        plot.margin=ggplot2::margin(1,1,1,1,"cm")) +
  expand_limits(x = 5.25) +
  labs(x="State",y="Broadband Usage",
       subtitle="Comparision of broadband usage across five U.S. States\n")

# comparing five states

# availability 
s1 = ggstatsplot::ggbetweenstats(
  data=broadband_pop, 
               x= st, y=broadband_availability_per_fcc,
               title="Distribution of broadband availability",
               package="wesanderson",
               palette="Darjeeling1") +
  ggplot2::theme(plot.margin=ggplot2::margin(1,1,1,1,"cm"))

# usage 
s2 = ggstatsplot::ggbetweenstats(
  data=broadband_pop, 
               x= st, y=broadband_usage,
               title="Distribution of broadband usage",
               package="wesanderson",
               palette="Darjeeling1") +
  ggplot2::theme(plot.margin=ggplot2::margin(1,1,1,1,"cm"))
s1 | s2

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMjIFRpZHkgVHVlc2RheSBXZWVrIDIwIApbSW50ZXJuZXQgQWNjZXNzLCBVUyBCcm9hZGJhbmRdKGh0dHBzOi8vZ2l0aHViLmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvYmxvYi9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMDUtMTEvcmVhZG1lLm1kKSwgZGF0YSBmcm9tIFtNaWNyb3NvZnRdKGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvVVNCcm9hZGJhbmRVc2FnZVBlcmNlbnRhZ2VzKSBieSB3YXkgb2YgW1RoZSBWZXJnZV0oaHR0cHM6Ly93d3cudGhldmVyZ2UuY29tLzIyNDE4MDc0L2Jyb2FkYmFuZC1nYXAtYW1lcmljYS1tYXAtY291bnR5LW1pY3Jvc29mdC1kYXRhKS4KClRpZHlUdWVzZGF5IHdlZWsgMjAgfCBEYXRhIGZyb20gTWljcm9zb2Z0IGFuZCBUaGUgVmVyZ2UgCgojIyMjIERhdGEgZGVmaW5pdGlvbgoKfCB2YXJpYWJsZSAgICAgICAgICAgICAgICAgICAgICAgfCBjbGFzcyAgICAgfCBkZXNjcmlwdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8IHN0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IGNoYXJhY3RlciB8IDIgbGV0dGVyIGFiYnJldmlhdGlvbiBvZiBzdGF0ZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgICBodHRwczovL3d3dy5pc28ub3JnL29icC91aS8jaXNvOmNvZGU6MzE2NjpVUyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCBjb3VudHlfaWQgICAgICAgICAgICAgICAgICAgICAgfCBkb3VibGUgICAgfCA0IHRvIDUgZGlnaXQgY29kZSB1c2VkIHRvIHJlcHJlc2VudCB0aGUgY291bnR5IChsYXN0IDMgZGlnaXRzKSBhbmQgdGhlIHN0YXRlIChmaXJzdCBkaWdpdCBvciBmaXJzdCAyIGRpZ2l0cykgICAgaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9nZW9ncmFwaGllcy9yZWZlcmVuY2UtZmlsZXMuaHRtbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgY291bnR5X25hbWUgICAgICAgICAgICAgICAgICAgIHwgY2hhcmFjdGVyIHwgQ291bnR5IE5hbWUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGJyb2FkYmFuZF9hdmFpbGFiaWxpdHlfcGVyX2ZjYyB8IGNoYXJhY3RlciB8IHBlcmNlbnQgb2YgcGVvcGxlIHBlciBjb3VudHkgd2l0aCBhY2Nlc3MgdG8gZml4ZWQgdGVycmVzdHJpYWwgYnJvYWRiYW5kIGF0IHNwZWVkcyBvZiAyNSBNYnBzLzMgTWJwcyBhcyBvZiB0aGUgZW5kIG9mIDIwMTcgICBodHRwczovL3d3dy5mY2MuZ292L2RvY3VtZW50L2Jyb2FkYmFuZC1kZXBsb3ltZW50LXJlcG9ydC1kaWdpdGFsLWRpdmlkZS1uYXJyb3dpbmctc3Vic3RhbnRpYWxseS0wIHwKfCBicm9hZGJhbmRfdXNhZ2UgICAgICAgICAgICAgICAgfCBjaGFyYWN0ZXIgfCBwZXJjZW50IG9mIHBlb3BsZSBwZXIgY291bnR5IHRoYXQgdXNlIHRoZSBpbnRlcm5ldCBhdCBicm9hZGJhbmQgc3BlZWRzIGJhc2VkIG9uIHRoZSBtZXRob2RvbG9neSBleHBsYWluZWQgYWJvdmUuIERhdGEgaXMgZnJvbSBOb3ZlbWJlciAyMDE5LiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CgojIyMgVmlzdWFsaXphdGlvbiAgCgpgYGB7ciwgbWVzc2FnZT1GfQojIGxvYWQgbGliYXJpZXMgCmxpYnJhcnkodGlkeXR1ZXNkYXlSKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh1cmJubWFwcikKbGlicmFyeSh1cmJudGhlbWVzKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoY29sb3JzcGFjZSkKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZ2dzdGF0c3Bsb3QpCmBgYAoKCmBgYHtyfQojIGltcG9ydCBkYXRhCmJyb2FkYmFuZCA8LSByZWFkcjo6cmVhZF9jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvbWFzdGVyL2RhdGEvMjAyMS8yMDIxLTA1LTExL2Jyb2FkYmFuZC5jc3YnKQpgYGAKCmBgYHtyfQojIGNsZWFuIGRhdGEgCiMgcmVmZXJlbmNlOiBKZXNzZSBNb3N0aXBhayAgCmJyb2FkYmFuZCA9IGJyb2FkYmFuZCAlPiUgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKQpnbGltcHNlKGJyb2FkYmFuZCkKCmJyb2FkYmFuZCA9IGJyb2FkYmFuZCAlPiUgbXV0YXRlKGJyb2FkYmFuZF91c2FnZT0gYXMubnVtZXJpYyhicm9hZGJhbmRfdXNhZ2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicm9hZGJhbmRfYXZhaWxhYmlsaXR5X3Blcl9mY2MgPSBhcy5udW1lcmljKGJyb2FkYmFuZF9hdmFpbGFiaWxpdHlfcGVyX2ZjYykpCmBgYAoKYGBge3J9CiMgdXMgY291bnRpZXMgc2hwIApjb3VudGllc19zZiA8LSBnZXRfdXJibl9tYXAoImNvdW50aWVzIiwgc2YgPSBUUlVFKQpgYGAKCgojIyMgVS5TLiBBdmFpbGFiaWxpdHkgYW5kIFVzYWdlIGJ5IENvdW50eQoKYGBge3J9CiMgYXZhaWxhYmlsaXR5IGJ5IGNvdW50eQpwMSA9IGNvdW50aWVzX3NmICU+JSAKICBsZWZ0X2pvaW4oYnJvYWRiYW5kLCBieT0iY291bnR5X25hbWUiKSAlPiUKICAjZmlsdGVyKHN0PT0iQ0EiKSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fc2YobWFwcGluZyA9IGFlcyhmaWxsID0gYnJvYWRiYW5kX2F2YWlsYWJpbGl0eV9wZXJfZmNjKSwKICAgICAgICAgIGNvbG9yID0gIiNmZmZmZmYiLCBzaXplID0gMC4yNSkgKwogIGNvb3JkX3NmKGRhdHVtID0gTkEpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obGFiZWxzID0gc2NhbGVzOjpwZXJjZW50LAogICAgICAgICAgICAgICAgICAgICAgIGNvbG91cnMgPSB3ZXNfcGFsZXR0ZSgiWmlzc291MSIsIDEwMCwgdHlwZSA9ICJjb250aW51b3VzIiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlPSJncmV5ODkiLAogICAgICAgICAgICAgICAgICAgICAgIHRyYW5zPSJyZXZlcnNlIikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApICsgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZT1lbGVtZW50X3RleHQoc2l6ZT05KSwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE0KSkgKyAKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG9yYmFyKHRpdGxlLnBvc2l0aW9uID0gInRvcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmhqdXN0ID0gLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldmVyc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXJoZWlnaHQgPSB1bml0KDEwLCAibGluZXMiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFyd2lkdGggPSB1bml0KC41LCAibGluZXMiKSkpICsKICBsYWJzKGZpbGw9IiIsCiAgICAgICB0aXRsZT0iVS5TLiBCcm9hZGJhbmQgQXZhaWxhYmlsaXR5IGJ5IENvdW50eSIsCiAgICAgICBzdWJ0aXRsZT0iUGVyY2VudCBvZiBwZW9wbGUgcGVyIGNvdW50eSB3aXRoIGFjY2VzcyB0byBmaXhlZCB0ZXJyZXN0cmlhbCBicm9hZGJhbmQgYXQgc3BlZWRzIG9mIDI1IE1icHMvMyBNYnBzLCBhcyBvZiB0aGUgZW5kIG9mIDIwMTciKQoKIyB1c2FnZSBieSBjb3VudHkKcDIgPSBjb3VudGllc19zZiAlPiUgCiAgbGVmdF9qb2luKGJyb2FkYmFuZCwgYnk9ImNvdW50eV9uYW1lIikgJT4lCiAgI2ZpbHRlcihzdD09IkNBIikgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX3NmKG1hcHBpbmcgPSBhZXMoZmlsbCA9IGJyb2FkYmFuZF91c2FnZSksCiAgICAgICAgICBjb2xvciA9ICIjZmZmZmZmIiwgc2l6ZSA9IDAuMjUpICsKICBjb29yZF9zZihkYXR1bSA9IE5BKSArIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXJzID0gd2VzX3BhbGV0dGUoIlppc3NvdTEiLCAxMDAsIHR5cGUgPSAiY29udGludW91cyIpLCAKICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZT0iZ3JleTg5IiwKICAgICAgICAgICAgICAgICAgICAgICB0cmFucz0icmV2ZXJzZSIpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArIAogIHRoZW1lKHBsb3Quc3VidGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNCkpICsgCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvcmJhcih0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS5oanVzdCA9IC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZlcnNlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFyaGVpZ2h0ID0gdW5pdCgxMCwgImxpbmVzIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcndpZHRoID0gdW5pdCguNSwgImxpbmVzIikpKSArCiAgbGFicyhmaWxsPSIiLAogICAgICAgdGl0bGU9IlUuUy4gQnJvYWRiYW5kIFVzYWdlIGJ5IENvdW50eSIsCiAgICAgICBzdWJ0aXRsZT0iUGVyY2VudCBvZiBwZW9wbGUgcGVyIGNvdW50eSB0aGF0IHVzZSB0aGUgaW50ZXJuZXQgYXQgYnJvYWRiYW5kIHNwZWVkcyBvZiAyNSBNYnBzLzMgTWJwcywgYXMgb2YgTm92ZW1iZXIgMjAxOSIpCgoKYGBgCgoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTV9CnAxLyBwMiArIHBsb3RfYW5ub3RhdGlvbihjYXB0aW9uPSdUaWR5VHVlc2RheSB3ZWVrIDIwIHwgRGF0YSBmcm9tIFRoZSBNaWNyb3NvZnQnKSAmIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQpgYGAKCgojIyMgVGV4YXM6IEJyb2FkYmFuZCBBdmFpbGFiaWxpdHkgYW5kIFVzYWdlCiogc2hhcmVkIG9uIFtUd2l0dGVyXShodHRwczovL3R3aXR0ZXIuY29tL2xlZW9sbmV5My9zdGF0dXMvMTM5MjAwMTIzOTg3Mzk0OTY5Ny9waG90by8xKQoKYGBge3J9CiMgYXZhaWxhYmlsaXR5IFRleGFzCnBsb3QxID0gY291bnRpZXNfc2YgJT4lIGZpbHRlcihzdGF0ZV9hYmJ2PT0iVFgiKSAlPiUKICBsZWZ0X2pvaW4oYnJvYWRiYW5kLCBieT0iY291bnR5X25hbWUiKSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fc2YobWFwcGluZyA9IGFlcyhmaWxsID0gYnJvYWRiYW5kX2F2YWlsYWJpbGl0eV9wZXJfZmNjKSwKICAgICAgICAgIGNvbG9yID0gIiNmZmZmZmYiLCBzaXplID0gMC4yNSkgKwogIGNvb3JkX3NmKGRhdHVtID0gTkEpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obGFiZWxzID0gc2NhbGVzOjpwZXJjZW50LAogICAgICAgICAgICAgICAgICAgICAgIGNvbG91cnMgPSB3ZXNfcGFsZXR0ZSgiWmlzc291MSIsIDEwMCwgdHlwZSA9ICJjb250aW51b3VzIiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlPSJncmV5ODkiLAogICAgICAgICAgICAgICAgICAgICAgIHRyYW5zPSJyZXZlcnNlIikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApICsgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZT1lbGVtZW50X3RleHQoc2l6ZT05KSwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE0KSkgKyAKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG9yYmFyKHRpdGxlLnBvc2l0aW9uID0gInRvcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmhqdXN0ID0gLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldmVyc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXJoZWlnaHQgPSB1bml0KDEwLCAibGluZXMiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFyd2lkdGggPSB1bml0KC41LCAibGluZXMiKSkpICsKICBsYWJzKGZpbGw9IiIsCiAgICAgICB0aXRsZT0iQnJvYWRiYW5kIEF2YWlsYWJpbGl0eSBJbiBUZXhhcywgVS5TLiIsCiAgICAgICBzdWJ0aXRsZT0iUGVyY2VudCBvZiBwZW9wbGUgcGVyIGNvdW50eSB3aXRoIGFjY2VzcyB0byBmaXhlZCB0ZXJyZXN0cmlhbCBicm9hZGJhbmQgYXQgc3BlZWRzXG5vZiAyNSBNYnBzLzMgTWJwcywgYXMgb2YgdGhlIGVuZCBvZiAyMDE3IikKCiMgVXNhZ2UgVGV4YXMKcGxvdDIgPSBjb3VudGllc19zZiAlPiUgZmlsdGVyKHN0YXRlX2FiYnY9PSJUWCIpICU+JQogIGxlZnRfam9pbihicm9hZGJhbmQsIGJ5PSJjb3VudHlfbmFtZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9zZihtYXBwaW5nID0gYWVzKGZpbGwgPSBicm9hZGJhbmRfdXNhZ2UpLAogICAgICAgICAgY29sb3IgPSAiI2ZmZmZmZiIsIHNpemUgPSAwLjI1KSArCiAgY29vcmRfc2YoZGF0dW0gPSBOQSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50bihsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgY29sb3VycyA9IHdlc19wYWxldHRlKCJaaXNzb3UxIiwgMTAwLCB0eXBlID0gImNvbnRpbnVvdXMiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWU9ImdyZXk4OSIsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhbnM9InJldmVyc2UiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkgKyAKICB0aGVtZShwbG90LnN1YnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTkpLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTQpKSArIAogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3JiYXIodGl0bGUucG9zaXRpb24gPSAidG9wIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUuaGp1c3QgPSAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJzZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcmhlaWdodCA9IHVuaXQoMTAsICJsaW5lcyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXJ3aWR0aCA9IHVuaXQoLjUsICJsaW5lcyIpKSkgKwogIGxhYnMoZmlsbD0iIiwKICAgICAgIHRpdGxlPSJCcm9hZGJhbmQgVXNhZ2UgSW4gVGV4YXMsIFUuUy4iLAogICAgICAgc3VidGl0bGU9IlBlcmNlbnQgb2YgcGVvcGxlIHBlciBjb3VudHkgdGhhdCB1c2UgdGhlIGludGVybmV0IGF0IGJyb2FkYmFuZCBzcGVlZHMgb2ZcbjI1IE1icHMvMyBNYnBzLCBhcyBvZiBOb3ZlbWJlciAyMDE5IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NX0KcGxvdDEvIHBsb3QyICsgcGxvdF9hbm5vdGF0aW9uKGNhcHRpb249J1RpZHlUdWVzZGF5IHdlZWsgMjAgfCBEYXRhIGZyb20gTWljcm9zb2Z0JykgJiB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41KSkKYGBgCgoKCiMgQnJvYWRiYW5kIEF2YWlsYWJpbGl0eSBieSBTdGF0ZQoKYGBge3IsIHdhcm5pbmc9RiwgZmlnLndpZHRoPTMuNSwgZmlnLmhlaWdodD0zLjV9CmJyb2FkYmFuZCAlPiUgZHJvcF9uYSgpICU+JSBncm91cF9ieShzdCkgJT4lCiAgc3VtbWFyaXNlKG1lZCA9IG1lZGlhbihicm9hZGJhbmRfdXNhZ2UpKSAtPiB0YWJsZV9tZWRpYW4KCiMgYm94cGxvdCBvZiBicm9hZGJhbmQgdXNhZ2UgYnkgc3RhdGUKYnJvYWRiYW5kICU+JSBkcm9wX25hKCkgJT4lCiAgZ2dwbG90KGFlcyh4PXJlb3JkZXIoc3QsYnJvYWRiYW5kX3VzYWdlKSwgeT1icm9hZGJhbmRfdXNhZ2UpKSArIAogIGdlb21fYm94cGxvdChjb2xvcj0iZ3JleTYwIikgKyAKICBnZW9tX3BvaW50KGRhdGE9dGFibGVfbWVkaWFuLCBhZXMoeD0gc3QsIHk9bWVkLCBmaWxsPW1lZCksIHNoYXBlPTIzLCBjb2xvcj0ic2xhdGVncmV5IixzaG93LmxlZ2VuZD1GKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZT0iVmlyaWRpcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWw9c2NhbGVzOjpwZXJjZW50KSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemU9MTApICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9mbGlwKCkKYGBgCgoKCmBgYHtyLCBmaWcud2lkdGg9My41LCBmaWcuaGVpZ2h0PTIuNX0KIyB1c2FnZSA1IHN0YXRlcwoKIyBnZW9tX2ZsYXRfdmlvbGluIGZ1bmN0aW9uIGZyb206IGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2RncnR3by9lYjc3NTBlNzQ5OTc4OTFkN2MyMAojIHJlZmVyZW5jZTogaHR0cHM6Ly9uZXVyb2NvbnNjaWVuY2Uud29yZHByZXNzLmNvbS8yMDE4LzAzLzE1L2ludHJvZHVjaW5nLXJhaW5jbG91ZC1wbG90cy8KIyByZWZlcmVuY2U6IGh0dHBzOi8vYml0c2FuZGdlbi5lcy9teS1maXJzdC1zaGlueS1hcHAtcmFpbmNsb3VkcGxvdHMvCgpwb3AgPSBjKCJDQSIsIlRYIiwiRkwiLCJOWSIsICJQQSIpICMgc3RhdGVzIGZvciBwbG90CmJyb2FkYmFuZF9wb3AgPSBicm9hZGJhbmQgJT4lIGZpbHRlcihzdCAlaW4lIHBvcCkKCmJyb2FkYmFuZF9wb3AgJT4lCiAgZ2dwbG90KGFlcyh4PWZjdF9yZXYoc3QpLCAKICAgICAgICAgICAgIHk9YnJvYWRiYW5kX3VzYWdlLCBmaWxsPXN0LCBjb2xvcj1zdCkpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXIoMC4xNSksc2l6ZT0xLjUsIGFscGhhPTAuNixzaGFwZT1hcy5udW1lcmljKDE2KSkgKyAKICBnZW9tX2ZsYXRfdmlvbGluKHBvc2l0aW9uPSBwb3NpdGlvbl9udWRnZSh4PTAuMjUsIHk9MCksYWRqdXN0PTIsYWxwaGE9MC45LCB0cmltPSdUUlVFJyxzY2FsZT0nd2lkdGgnKSArCiAgZ2VvbV9ib3hwbG90KGFlcyh4PXN0LHk9YnJvYWRiYW5kX3VzYWdlLGZpbGw9c3QpLCBwb3NpdGlvbj1wb3NpdGlvbl9udWRnZSh4PTAuMjUsIHk9MCksCiAgICAgICAgICAgICAgIHdpZHRoPTAuMSwgb3V0bGllci5zaGFwZSA9IE5BLCB2YXJ3aWR0aD1GQUxTRSwgY29sb3I9ImJsYWNrIiwgYWxwaGE9MC4zKSArIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbD1zY2FsZXM6OnBlcmNlbnQpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiIzU4OGI4YiIsIiNmMjhmM2IiLCIjNDU3YjlkIiwiI2M4NTUzZCIsIiM1YjVmOTciKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjNTg4YjhiIiwiI2YyOGYzYiIsIiM0NTdiOWQiLCIjYzg1NTNkIiwiIzViNWY5NyIpKSArCiAgY29vcmRfZmxpcCgpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsCiAgICAgICAgcGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICBwbG90LnN1YnRpdGxlPWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgc2l6ZT0xMCksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT05LCBmYWNlPSJib2xkIiksCiAgICAgICAgcGxvdC5tYXJnaW49Z2dwbG90Mjo6bWFyZ2luKDEsMSwxLDEsImNtIikpICsKICBleHBhbmRfbGltaXRzKHggPSA1LjI1KSArCiAgbGFicyh4PSJTdGF0ZSIseT0iQnJvYWRiYW5kIFVzYWdlIiwKICAgICAgIHN1YnRpdGxlPSJDb21wYXJpc2lvbiBvZiBicm9hZGJhbmQgdXNhZ2UgYWNyb3NzIGZpdmUgVS5TLiBTdGF0ZXNcbiIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTN9CiMgY29tcGFyaW5nIGZpdmUgc3RhdGVzCgojIGF2YWlsYWJpbGl0eSAKczEgPSBnZ3N0YXRzcGxvdDo6Z2diZXR3ZWVuc3RhdHMoCiAgZGF0YT1icm9hZGJhbmRfcG9wLCAKICAgICAgICAgICAgICAgeD0gc3QsIHk9YnJvYWRiYW5kX2F2YWlsYWJpbGl0eV9wZXJfZmNjLAogICAgICAgICAgICAgICB0aXRsZT0iRGlzdHJpYnV0aW9uIG9mIGJyb2FkYmFuZCBhdmFpbGFiaWxpdHkiLAogICAgICAgICAgICAgICBwYWNrYWdlPSJ3ZXNhbmRlcnNvbiIsCiAgICAgICAgICAgICAgIHBhbGV0dGU9IkRhcmplZWxpbmcxIikgKwogIGdncGxvdDI6OnRoZW1lKHBsb3QubWFyZ2luPWdncGxvdDI6Om1hcmdpbigxLDEsMSwxLCJjbSIpKQoKIyB1c2FnZSAKczIgPSBnZ3N0YXRzcGxvdDo6Z2diZXR3ZWVuc3RhdHMoCiAgZGF0YT1icm9hZGJhbmRfcG9wLCAKICAgICAgICAgICAgICAgeD0gc3QsIHk9YnJvYWRiYW5kX3VzYWdlLAogICAgICAgICAgICAgICB0aXRsZT0iRGlzdHJpYnV0aW9uIG9mIGJyb2FkYmFuZCB1c2FnZSIsCiAgICAgICAgICAgICAgIHBhY2thZ2U9Indlc2FuZGVyc29uIiwKICAgICAgICAgICAgICAgcGFsZXR0ZT0iRGFyamVlbGluZzEiKSArCiAgZ2dwbG90Mjo6dGhlbWUocGxvdC5tYXJnaW49Z2dwbG90Mjo6bWFyZ2luKDEsMSwxLDEsImNtIikpCmBgYAoKYGBge3IsIGZpZy53aWR0aD03fQpzMSB8IHMyCmBgYAoKCgoKCgoKCgoKCgo=